package com.atguigu.yygh.order.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.atguigu.yygh.common.exception.YyghException;
import com.atguigu.yygh.common.result.R;
import com.atguigu.yygh.common.result.ResultCode;
import com.atguigu.yygh.common.result.ResultCodeEnum;
import com.atguigu.yygh.enums.OrderStatusEnum;
import com.atguigu.yygh.enums.PaymentTypeEnum;
import com.atguigu.yygh.enums.RefundStatusEnum;
import com.atguigu.yygh.model.order.OrderInfo;
import com.atguigu.yygh.model.order.PaymentInfo;
import com.atguigu.yygh.model.order.RefundInfo;
import com.atguigu.yygh.order.mapper.OrderInfoMapper;
import com.atguigu.yygh.order.service.OrderInfoService;
import com.atguigu.yygh.order.service.PaymentInfoService;
import com.atguigu.yygh.order.service.RefundInfoService;
import com.atguigu.yygh.order.service.WxPayService;
import com.atguigu.yygh.order.utils.ConstantProperties;
import com.atguigu.yygh.order.utils.HttpClientUtils;
import com.atguigu.yygh.order.utils.HttpRequestHelper;
import com.github.wxpay.sdk.WXPayConstants;
import com.github.wxpay.sdk.WXPayUtil;
import lombok.extern.slf4j.Slf4j;

import org.joda.time.DateTime;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * Created with IntelliJ IDEA
 *
 * @Date: 2023/1/6 - 16:00
 * @Author: Hyoung
 * @Description:
 */
@Service
@Slf4j
public class WxPayServiceImpl implements WxPayService {
    @Autowired
    private OrderInfoMapper orderInfoMapper;

    @Autowired
    private ConstantProperties constantProperties;

    @Autowired
    private OrderInfoService orderInfoService;

    @Autowired
    private PaymentInfoService paymentInfoService;

    @Autowired
    private RefundInfoService refundInfoService;

    @Override
    public boolean queryPayStatus(Long orderId) {

        try {
            // 根据orderId获取订单
            OrderInfo orderInfo = orderInfoMapper.selectById(orderId);

            // 调用微信端的查单接口

            HashMap<String, String> params = new HashMap<>();
            params.put("appid", constantProperties.getAppId());//公众账号ID
            params.put("mch_id", constantProperties.getPartner());//商户号
            params.put("out_trade_no", orderInfo.getOutTradeNo()); //商户订单号
            params.put("nonce_str", WXPayUtil.generateNonceStr()); //随机字符串
            String xmlParams = WXPayUtil.generateSignedXml(params, constantProperties.getPartnerKey());

            // 发送请求
            HttpClientUtils client = new HttpClientUtils("https://api.mch.weixin.qq.com/pay/orderquery");
            client.setXmlParam(xmlParams);
            client.setHttps(true);
            client.post();

            // 获取结果
            String resultXml = client.getContent();
            // 解析结果
            Map<String, String> resultMap = WXPayUtil.xmlToMap(resultXml);
            //错误处理
            if ("FAIL".equals(resultMap.get("return_code")) || "FAIL".equals(resultMap.get("result_code"))) {
                log.error("错误：" + resultXml);
                throw new YyghException(ResultCode.ERROR, resultMap.get("err_code_des"));
            }
            // 如果支付成功
            if ("SUCCESS".equals(resultMap.get("trade_state"))) {
                // 修改订单状态
                // 确认接口调用的幂等性，反复调用接口不会对结果产生影响
                synchronized (this) {
                    orderInfo = orderInfoMapper.selectById(orderId);
                    if (orderInfo.getOrderStatus().equals(OrderStatusEnum.PAID.getStatus())) {
                        return true;
                    }
                    orderInfoService.updateStatusById(orderId, OrderStatusEnum.PAID.getStatus());

                }
                // 记录支付日志
                paymentInfoService.savePaymentInfo(orderInfo, resultMap);
                // 通知医院端同步
                HashMap<String, Object> paramsMap = new HashMap<>();
                paramsMap.put("hoscode", orderInfo.getHoscode());
                paramsMap.put("hosRecordId", orderInfo.getHosRecordId());
                paramsMap.put("timestamp", HttpRequestHelper.getTimestamp());

                String hospHost = "http://locahost:9998";
                String signKey = "c241f851124077d736415206ace167cb";
                paramsMap.put("sign", HttpRequestHelper.getSign(paramsMap, signKey));

                // 发送请求
                JSONObject result = HttpRequestHelper.sendRequest(paramsMap, hospHost + "/order/updatePayStatus");

                if (!result.getInteger("code").equals(ResultCodeEnum.SUCCESS.getCode())) {
                    throw new YyghException(ResultCode.ERROR, "查单失败");
                }
                // 返回结果
                return true;
            }
            return false;
        } catch (Exception e) {
            throw new YyghException(ResultCode.ERROR, "查单失败", e);
        }

    }

    @Override
    public String createNative(Long orderId, String remoteAddr) {

        try {
            // 获取订单
            OrderInfo orderInfo = orderInfoMapper.selectById(orderId);

            HashMap<String, String> params = new HashMap<>();
            params.put("appid", constantProperties.getAppId());//公众账号ID
            params.put("mch_id", constantProperties.getPartner());//商户号
            params.put("nonce_str", WXPayUtil.generateNonceStr()); //随机字符串
            String dateTimeString = new DateTime(orderInfo.getReserveDate()).toString("yyyy-MM-dd");
            String hospname = orderInfo.getHosname();
            String depname = orderInfo.getDepname();
            params.put("body", dateTimeString + hospname + depname + "挂号费"); //商品描述
            params.put("out_trade_no", orderInfo.getOutTradeNo()); //商户订单号
            BigDecimal total = orderInfo.getAmount().multiply(new BigDecimal(100));
            params.put("total_fee", "1" /*total.toString()*/); //标价金额，单位为分
            params.put("spbill_create_ip", remoteAddr); //终端IP
            params.put("notify_url", constantProperties.getNotifyUrl()); //通知地址
            params.put("trade_type", "NATIVE"); //交易类型

//            String signature = WXPayUtil.generateSignature(params, constantProperties.getPartnerKey());
//            params.put("sign", signature);//签名
//            String xmlParams = WXPayUtil.mapToXml(params);//将参数转换成xml字符串
            //生成签名并追加到参数中，最后将参数集合转换成xml字符串
            String xmlParams = WXPayUtil.generateSignedXml(params, constantProperties.getPartnerKey());

            //发送请求
            HttpClientUtils client = new HttpClientUtils("https://api.mch.weixin.qq.com/pay/unifiedorder");
            client.setXmlParam(xmlParams);
            client.setHttps(true);
            client.post();

            String resultXml = client.getContent();
            Map<String, String> resultMap = WXPayUtil.xmlToMap(resultXml);
            if ("FAIL".equals(resultMap.get("return_code")) || "FAIL".equals(resultMap.get("result_code"))) {
                log.info("错误" + resultXml);
                throw new YyghException(ResultCode.ERROR, resultMap.get("err_code_des"));
            }
            return resultMap.get("code_url");
        } catch (YyghException e) {
            throw e;
        } catch (Exception e) {
            throw new YyghException(ResultCode.ERROR, "获取微信支付二维码失败", e);
        }
    }

    @Override
    public void refund(Long orderId) {

        try {
//        OrderInfo orderInfo = orderInfoMapper.selectById(orderId);
//        String outTradeNo = orderInfo.getOutTradeNo();

            PaymentInfo paymentInfo = paymentInfoService.getPaymentInfo(orderId, PaymentTypeEnum.WEIXIN.getStatus());
            String outTradeNo = paymentInfo.getOutTradeNo();
//        String tradeNo = paymentInfo.getTradeNo();

            //保存退款记录
            RefundInfo refundInfo = refundInfoService.saveRefundInfo(paymentInfo);
//        OrderInfo orderInfo = orderInfoMapper.selectById(orderId);
//        String outTradeNo = orderInfo.getOutTradeNo();
            Map<String, String> params = new HashMap<>();
            params.put("appid", constantProperties.getAppId()); //公众账号ID
            params.put("mch_id", constantProperties.getPartner()); //商户编号
            params.put("nonce_str", WXPayUtil.generateNonceStr()); //随机数
//        params.put("transaction_id", tradeNo); //微信订单号
            params.put("out_trade_no", outTradeNo); //商户订单编号
            params.put("out_refund_no", "tk" + paymentInfo.getOutTradeNo()); //商户退款单号
            params.put("total_fee", "1"); //测试
            params.put("refund_fee", "1"); //测试
            HttpClientUtils client = new HttpClientUtils("https://api.mch.weixin.qq.com/secapi/pay/refund");
            //将参数转换成xml字符串格式：生成带有签名的xml格式字符串
            String xmlParams = WXPayUtil.generateSignedXml(params, constantProperties.getPartnerKey());
            client.setXmlParam(xmlParams);//将参数放入请求对象的方法体
            client.setHttps(true);//使用https形式发送
            client.setCert(true); //使用证书
            client.setCertPassword(constantProperties.getPartner()); //证书密码
            client.setCertPath(constantProperties.getCert()); //证书路径
            client.post();//发送请求

            String resultXml = client.getContent();
            Map<String, String> resultMap = WXPayUtil.xmlToMap(resultXml);
            if (WXPayConstants.SUCCESS.equals(resultMap.get("return_code")) && WXPayConstants.SUCCESS.equals(resultMap.get("result_code"))) {
                //更新退款记录
                refundInfo.setCallbackTime(new Date());
                refundInfo.setTradeNo(resultMap.get("refund_id"));
                refundInfo.setRefundStatus(RefundStatusEnum.REFUND.getStatus());
                refundInfo.setCallbackContent(JSONObject.toJSONString(resultMap));
                refundInfoService.updateById(refundInfo);
            } else {
                log.error("申请退款失败：" + resultXml);
                throw new YyghException(ResultCode.ERROR, "申请退款失败");
            }

        } catch (Exception e) {
            throw new YyghException(ResultCode.ERROR, "退款失败", e);
        }

    }
}
